package com.wzdigit.wms.wms.rpc.inventory;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.wzdigit.framework.Shift;
import com.wzdigit.mes.basic.api.BasicGetCustomerApi;
import com.wzdigit.wms.basic.domain.basic.Sku;
import com.wzdigit.wms.basic.domain.inventory.Goods;
import com.wzdigit.wms.basic.domain.inventory.Lotno;
import com.wzdigit.wms.basic.enums.GoodsStatusEnum;
import com.wzdigit.wms.basic.mapper.core.basic.LotAttrMapper;
import com.wzdigit.wms.basic.mapper.core.basic.SkuMapper;
import com.wzdigit.wms.basic.mapper.core.inventory.GoodsMapper;
import com.wzdigit.wms.wms.api.inventory.GoodsApi;
import com.wzdigit.wms.wms.dto.inventory.GoodsDto;
import com.wzdigit.wms.basic.service.code.LotnoService;
import com.wzdigit.wms.wms.service.task.GoodsDtoService;
import lombok.extern.slf4j.Slf4j;
import net.dreamlu.mica.core.utils.BeanUtil;
import net.dreamlu.mica.core.utils.CollectionUtil;
import org.apache.dubbo.config.annotation.Reference;
import org.apache.dubbo.config.annotation.Service;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.concurrent.TimeUnit;

/**
 * @ClassName GoodsApiImplService
 * @Description 货品清单接口实现类
 * @Author LHR-PC
 * @Date 2021/1/21 21:37
 * @Version
 **/
@Slf4j
@Service(version = "${dubbo.providers.wms.goods.api:1.0.0}")
public class GoodsApiImplService implements GoodsApi {

    @Autowired
    private GoodsMapper goodsMapper;

    @Autowired
    private SkuMapper skuMapper;

    @Autowired
    private LotnoService lotnoService;

    @Autowired
    private RedissonClient redisson;

    @Autowired
    private LotAttrMapper lotAttrMapper;

    @Autowired
    private GoodsDtoService goodsDtoService;

    @Reference(version = "${dubbo.providers.basic.customer.api.version:1.0.0}", check = false, timeout = 300000)
    BasicGetCustomerApi basicGetCustomerApi;

    public static final String prefix ="DOWNLINE_";
    /**
     * 插入单条记录
     *
     * @param record
     * @return
     */
     @Override
     @Transactional(rollbackFor = Exception.class)
    public  void insert(GoodsDto record) {
        Goods goods = new Goods();
        BeanUtil.copyNonNull(record, goods);
        try {
            goodsDtoService.addOneGoods(null,record);
        }catch (Exception e){
            e.printStackTrace();

            String errMsg = record.getGoodsSn() + "下线同步失败"+e.toString();
            log.error(errMsg);
            throw new RuntimeException("wms同步失败");
        }
    }

    /**
     * 批量插入
     *
     * @param goodsDtoList
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public synchronized List<Integer> batchInsert(List<GoodsDto> goodsDtoList) throws Exception {
        Lotno lotno = null;
        log.info("入参:goodsDtoList的size:{}", String.valueOf(goodsDtoList.size()));
        log.info("goodsDtoList:" + goodsDtoList.toString());

        List<Integer> failureIds = new ArrayList<>();
        for (GoodsDto goodsDto : goodsDtoList) {
            try {
                goodsDtoService.addOneGoods(failureIds, goodsDto);
            }catch (Exception e){
                e.printStackTrace();
                failureIds.add(goodsDto.getGoodsId());

                String errMsg = goodsDto.getGoodsSn() + "下线同步失败";
                log.error(errMsg);
                throw new RuntimeException("wms同步失败"+errMsg);
            }
        }

        long count = goodsDtoList.stream().filter(i -> !failureIds.contains(i.getGoodsId())).count();
        log.info("----------- goods从QMS接收的数量: {} --------------------", count);
        return failureIds;
    }

    /**
     * 新增/更新一个新的GOODS
     * @param failureIds
     * @param goodsDto
     */
    /*@Transactional(rollbackFor = Exception.class)
    public void addOneGoods(List<Integer> failureIds, GoodsDto goodsDto) throws Exception {


        //加锁执行
        String key = prefix + goodsDto.getGoodsSn();
        log.info("key:{}", key);
        RLock lock = redisson.getLock(key);

        if (lock.tryLock(2500, TimeUnit.MILLISECONDS)) {

            log.info(Thread.currentThread().getName() + "抢到锁。执行业务");

            try {
                Lotno lotno;
                Sku sku = new Sku();

                if (goodsDto.getSkuCode() == null) {
                    String errMsg = goodsDto.getGoodsSn() + "下线同步失败,未传入SKU_CODE";
                    log.error(errMsg);
                    throw new RuntimeException(errMsg);
                }

                sku.setSkuCode(goodsDto.getSkuCode());
                Sku sku1 = skuMapper.selectOne(new QueryWrapper<>(sku));

                if (sku1 == null || sku1.getSkuId() == null) {
                    String msg = String.format("根据产品code:【%s】在货品主数据表WMS_SKU中未找到数据", goodsDto.getSkuCode());
                    log.warn(msg);

                    String errMsg = goodsDto.getGoodsSn() + "下线同步失败";
                    log.error(errMsg);
                    throw new RuntimeException(msg);
                }
                if (goodsDto.getMfgLine()==null||"".equals(goodsDto.getMfgLine())){
                    String msg = String.format("线体【%s】为空", goodsDto.getMfgLine());
                    log.warn(msg);

                    String errMsg = goodsDto.getGoodsSn() + "下线同步失败";
                    log.error(errMsg);
                    throw new RuntimeException(msg);
                }
                if (goodsDto.getPrdWo()==null||"".equals(goodsDto.getPrdWo())){
                    String msg = String.format("工单【%s】为空", goodsDto.getPrdWo());
                    log.warn(msg);

                    String errMsg = goodsDto.getGoodsSn() + "下线同步失败";
                    log.error(errMsg);
                    throw new RuntimeException(msg);
                }
                if (goodsDto.getFactory()==null||"".equals(goodsDto.getFactory())){
                    String msg = String.format("组织【%s】为空", goodsDto.getFactory());
                    log.warn(msg);

                    String errMsg = goodsDto.getGoodsSn() + "下线同步失败";
                    log.error(errMsg);
                    throw new RuntimeException(msg);
                }


                Goods goods = new Goods();
                BeanUtil.copyNonNull(goodsDto, goods);
                goods.setSkuId(sku1.getSkuId());
                goods.setUnit(sku1.getBaseUnit());
                goods.setIsHold(0);
                goods.setStatus(GoodsStatusEnum.CREATE.getCode());
                Goods record = goodsMapper.selectBySn(goods.getGoodsSn());

                //添加根据SN查询/设置货品，货主
                if (record != null && record.getGoodsId() != null) {
//                    Shift.fatal("["+record.getGoodsSn()+"]下线失败，必须先出库再返包!");
                    goods.setModifyUser("system");
                    goods.setModifyTime(new Date());
                    goods.setGoodsId(record.getGoodsId());

                    goodsMapper.updateById(goods);
                } else {
                    goods.setCreateTime(new Date());
                    goods.setCreateUser("system");
                    goodsMapper.insert(goods);

                    lotno = lotnoService.createLotnoBySn(goodsDto.getGoodsSn(), "system");

                    if (lotno == null) {

                        String msg = "【goods同步】生成批次号失败";
                        log.info(msg);
                        int i = goodsMapper.deleteById(goods.getGoodsId());

                        String errMsg = msg + goodsDto.getGoodsSn() + "下线同步失败";
                        log.error(errMsg);
                        throw new RuntimeException(errMsg);
                    }
                    goods.setLotno(lotno.getLotno());
                    goodsMapper.updateById(goods);
                }
                log.info("--------------- goods:" + goods + "-------------");
            } finally {
                lock.unlock();
                log.info(Thread.currentThread().getName() + "释放锁完成");
            }
        } else {
            log.info(Thread.currentThread().getName() + "没有抢到锁,相同条码重复写到WMS直接抛弃");
        }
    }*/

    public Boolean selectByGoodsSn(String goodSn){
        Goods goods = goodsMapper.selectBySn(goodSn);
        return  goods==null;
    }
}
